package com.cn.tianxin.ssserver.service;

import com.cn.tianxin.ssserver.ext.WXXCXAccessToken;
import com.cn.tianxin.ssserver.utils.HttpUtil;
import com.cn.tianxin.ssserver.utils.PropUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfigImpl;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

//微信小程序服务
@Service
public class WeixinXCXService {

    private static String appid;
    private static String secret;

    private static ObjectMapper mapper;

    private WXPayConfigImpl config;
    private WXPay wxPay;

    public WeixinXCXService() {
        try {
            config = WXPayConfigImpl.getInstance();
            wxPay = new WXPay(config, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static {
        try {
            appid = PropUtil.getPropUtilFromMap("weixin.properties").get("xcx_appid");
            secret = PropUtil.getPropUtilFromMap("weixin.properties").get("xcx_secret");
            mapper = new ObjectMapper();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //由小程序前台返回code，解析再从服务器获取登录凭证
    public Map<String, Object> code2Session(String code) throws IOException {

        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("js_code", code);
        reqMap.put("appid", appid);
        reqMap.put("secret", secret);
        reqMap.put("grant_type", "authorization_code");
        byte[] bytes = HttpUtil.httpRequest("https://api.weixin.qq.com/sns/jscode2session", reqMap);

        String string = new String(bytes, "UTF-8");
        Map map = mapper.readValue(string, Map.class);
        System.out.println("WeixinXCXService.code2Session=>map=>" + map);

        return map;
    }

    //根据code2Session 返回的结果，
    public Map<String, Object> getWXUserInfo(Map<String, Object> map) {

        try {
            if (map != null && map.get("access_token") != null && map.get("openid") != null) {

                String urlStr = "https://api.weixin.qq.com/sns/userinfo?access_token=" +
                        map.get("access_token") + "&openid=" + map.get("openid") + "&lang=zh_CN";

                byte[] bytes = HttpUtil.httpRequest(urlStr, (String) null, "GET");
                if (bytes == null) {
                    return null;
                }

                String resStr = new String(bytes, "UTF-8");
                Map resMap = mapper.readValue(resStr, Map.class);
                return resMap;
            } else {
                //code2Session 获取信息失败，直接返回这个信息
                return map;
            }

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }

    //企业付款到个人微信
    private Map<String, Object> enterprisePay(String appid, String openid, String redPackId, int money, String remark) throws Exception {
        Map<String, String> reqMap = new HashMap<>();

        reqMap.put("mch_appid", appid);
        reqMap.put("mchid", config.getMchID());
        reqMap.put("nonce_str", WXPayUtil.generateUUID());
        reqMap.put("partner_trade_no", redPackId);
        reqMap.put("openid", openid);
        reqMap.put("check_name", "NO_CHECK");
        reqMap.put("amount", String.format("%d", money));
        reqMap.put("desc", remark);
        reqMap.put("spbill_create_ip", PropUtil.getPropUtilFromMap("common.properties").get("spbill_create_ip"));
        //获取签名字符串
        String signature = WXPayUtil.generateSignature(reqMap, config.getKey());
        reqMap.put("sign", signature);

        String url = //"https://api.mch.weixin.qq.com" +
                "/mmpaymkttransfers/promotion/transfers";

        String resultStr = wxPay.requestWithCert(url, reqMap, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());

        System.out.println(resultStr);
        Map map = WXPayUtil.xmlToMap(resultStr);

        return map;

    }

    public static Set<String> redPackIdList = new HashSet<>();    //已尝试的红包记录、临时存储下

    public Map<String, Object> enterprisePay(String code, String redPackId) {

        //根据redPackId获取    兑换单(红包)对应的金额
        //String oid = "oIsr60D20qxvURuHklh8kMW2qNqM";//汪邻辉
        //String oid = "oIsr60D20qxvURuHklh8kMW2qNqM";//tx
        Map<String, Object> resultMap = new HashMap<>();

        //各种验证红包有效性
        if (redPackId == null || "".equals(redPackId.trim()) || "null".equals(redPackId)) {//微信bug，传过来的参数redPackId为空时，是redPackId=null这个！！fuck
            resultMap.put("state", "failed");
            resultMap.put("msg", "兑换单号为空");
            return resultMap;
        }

        // 检验红包是否被领取或取消
        // 兑换单状态(0:新建,1:微信用户已获取,2:取消,3:超时,4:异常)    //3超时不用状态判断，由创建时间和expire来判断

        // 检验红包时效性

        Map<String, Object> codeResult = null;
        try {
            codeResult = code2Session(code);
        } catch (IOException e) {
            e.printStackTrace();
            resultMap.put("state", "failed");
            resultMap.put("msg", "获取用户openid异常=>" + e.getMessage());
            return resultMap;
        }
        if (codeResult == null || codeResult.get("openid") == null) {
            resultMap.put("state", "failed");
            resultMap.put("msg", codeResult);
            return resultMap;
        }

        redPackIdList.add(redPackId);
        int money = 30;//3毛钱

        try {
            Map<String, Object> payMap = enterprisePay(appid, (String) codeResult.get("openid"), redPackId, money, "测试企业支付，兑换单号:" + redPackId);
            if (payMap != null && "SUCCESS".equals(payMap.get("return_code"))) {
                if ("SUCCESS".equals(payMap.get("result_code"))) {
                    resultMap.put("state", "success");
                    //模拟返回兑换单信息
                    resultMap.put("msg", mapper.readValue("{\"redPackId\":\"000002\",\"points\":3,\"money\":30,\"remark\":\"happy new year!\"}", Map.class));
                    return resultMap;
                } else {
                    resultMap.put("state", "failed");
                    resultMap.put("msg", String.format("企业付款-支付交易失败:(错误码:%s 描述:%s)", payMap.get("err_code"), payMap.get("err_code_des")));
                    return resultMap;
                }

            } else {
                resultMap.put("state", "failed");
                resultMap.put("msg", "企业付款-接口通讯失败:" + payMap.get("return_msg"));
                return resultMap;
            }
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("state", "failed");
            resultMap.put("msg", "企业付款-调用微信接口失败:" + e.getMessage());
            return resultMap;
        }

    }

    /**
     * 根据scene 参数，和跳转页面page生成二维码(请求微信服务器)
     * https://developers.weixin.qq.com/miniprogram/dev/api/getWXACodeUnlimit.html
     *
     * @param scene      二维码中给小程序页面传递的参数
     * @param page       小程序跳转页面
     * @param width
     * @param auto_color
     * @param line_color
     * @param is_hyaline
     * @return
     */
    private static Map<String, Object> generateWXXCXQRCode(String scene, String page,
                                                           Integer width, Boolean auto_color, Map<String, Object> line_color, Boolean is_hyaline) throws IOException {
        //生成微信小程序二维码
        Map<String, Object> resMap = new HashMap<>();

        if (scene == null || "".equals(scene) || page == null || "".equals(scene)) {
            return null;
        }

        Map line_colorMap = mapper.readValue("{\"r\":0,\"g\":0,\"b\":0}", Map.class);

        //获取token
        String access_token = WXXCXAccessToken.getToken().getAccess_token();
        width = (width != null) ? width : 430;    //二维码的宽度，单位 px，最小 280px，最大 1280px
        auto_color = (auto_color != null) ? auto_color : false;    //自动配置线条颜色，如果颜色依然是黑色，则说明不建议配置主色调，默认 false
        line_color = (line_color != null) ? line_color : line_colorMap;    //auto_color 为 false 时生效，使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示
        is_hyaline = (is_hyaline != null) ? is_hyaline : false;    //是否需要透明底色，为 true 时，生成透明底色的小程序

        String urlStr = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token;

        Map<String, Object> reqParam = new HashMap<>();
        reqParam.put("scene", scene);
        reqParam.put("page", page);
        reqParam.put("width", width);
        reqParam.put("auto_color", auto_color);
        if (!auto_color) {
            //非自动颜色，则设置line_color
            reqParam.put("line_color", line_color);
        }
        reqParam.put("is_hyaline", is_hyaline);

        byte[] bytes = HttpUtil.httpPostJSON(urlStr, mapper.writeValueAsString(reqParam));
        String resStr = new String(bytes, "UTF-8");

        if (resStr.contains("errcode")) {
            Map errMap = mapper.readValue(resStr, Map.class);
            resMap.put("state", "failed");
            resMap.put("errMap", errMap);
        } else {
            resMap.put("state", "success");
            resMap.put("data", bytes);
        }

        return resMap;
    }

    public static void main(String[] args) throws IOException {

        /*Map<String, Object> map = generateWXXCXQRCode("123456", "pages/redPack/redPack", null, null, null, null);
        System.out.println("map=>"+map);*/
        /*String access_token = WXXCXAccessToken.getToken().getAccess_token();
        System.out.println("access_token=>"+access_token);*/

        long l = System.currentTimeMillis();
        Random random = new Random();
        int i = random.nextInt(100);
        String randNoStr = "00" + i;
        randNoStr = randNoStr.substring(randNoStr.length() - 2);


        System.out.println("code=>" + l + "A" + randNoStr);

    }

}
